package com.yanqu.road.server.gameplayer.module.relatives;

import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eMailType;
import com.yanqu.road.entity.enums.ePlayerAttrType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.relatives.RelativesGift;
import com.yanqu.road.entity.relatives.RelativesInfo;
import com.yanqu.road.entity.relatives.RelativesLetter;
import com.yanqu.road.entity.union.cross.CrossUnionMember;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.RelativesPb;
import com.yanqu.road.pb.relatives.RelativesProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.relatives.RelativesMgr;
import com.yanqu.road.server.manger.union.CrossUnionMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.mina.util.ConcurrentHashSet;

import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 亲家模块
 */
public class RelativesModule extends GeneralModule {

    /**
     * 亲家数据
     */
    private Map<Long, RelativesInfo> relativesMap;

    /**
     * 书信数据
     */
    private Map<Long, LinkedList<RelativesLetter>> letterMap;

    /**
     * 赠送数据
     */
    private Map<Long, RelativesGift> giveMap;
    /**
     * 领取数据
     */
    private Map<Long, RelativesGift> receiveMap;

    /**
     * 需要显示的历史联姻玩家
     */
    private Set<Long> historyMarriageIds;


    public RelativesModule(GamePlayer player) {
        super(player);
    }

    public Map<Long, RelativesGift> getGiveMap() {
        return giveMap;
    }

    @Override
    public boolean loadData() {
        relativesMap = RelativesMgr.loadRelativesInfo(player.getUserId());
        letterMap = RelativesMgr.loadRelativesLetter(player.getUserId());
        giveMap = new ConcurrentHashMap<>();
        receiveMap = new ConcurrentHashMap<>();
        RelativesMgr.loadRelativesGift(player.getUserId(), giveMap, receiveMap);
        // 过滤解除的亲家的未领取的赠礼
        for (Long relativesId : receiveMap.keySet()) {
            if (!relativesMap.containsKey(relativesId) || (relativesMap.get(relativesId).getStatus() == 0 && !receiveMap.get(relativesId).isGet())) {
                receiveMap.remove(relativesId);
            }
        }
        historyMarriageIds = new ConcurrentHashSet<>();
        return true;
    }

    @Override
    public boolean afterLoadData() {
        for (Long relativesId : letterMap.keySet()) {
            checkReceiveLetterNum(relativesId);
        }
        return true;
    }

    @Override
    public boolean saveData() {
        return true;
    }

    @Override
    public void afterLogin() {
        syncRelativesData();
        syncGiftList();
    }

    @Override
    public void loginSendMsg() {

    }

    /**
     * 同步亲家信息
     */
    public void syncRelativesData() {
        RelativesProto.RelativesListMsg.Builder msg = RelativesProto.RelativesListMsg.newBuilder();
        if (relativesMap != null && !relativesMap.isEmpty()) {
            // 计算未读书信
            Map<Long, Integer> redMap = new HashMap<>();
            letterMap.forEach((k,v)->{
                if (v != null) {
                    int redNum = 0;
                    for (RelativesLetter letter : v) {
                        if (letter.isDelete()) {
                            continue;
                        }
                        if (!letter.isShow() && letter.getFromId() == k) {
                            redNum++;
                        }
                    }
                    redMap.put(k, redNum);
                }
            });

            List<Long> removeList = new ArrayList<>();
            for (Map.Entry<Long, Integer> entry : redMap.entrySet()) {
                RelativesInfo relativesInfo = relativesMap.get(entry.getKey());
                if(relativesInfo != null && relativesInfo.getStatus() == 0){
                    removeList.add(entry.getKey());
                }
            }
            for (Long key : removeList) {
                redMap.remove(key);
            }

            long serverId = GameServer.getInstance().getServerId();
            calHistoryMarriage();
            relativesMap.forEach((k,v)->{
                if (v.getStatus() == 1 || historyMarriageIds.contains(k)) {
                    Integer red = redMap.get(k);
                    if (red == null) {
                        red = 0;
                    }
                    long relativesServerId = RelativesMgr.getUserServerId(k);
                    UserBaseInfo relatives;
                    if(relativesServerId == serverId){
                        relatives = UserMgr.getUserBaseInfo(k, serverId);
                    }else {
                        relatives = RelativesMgr.getCacheOtherServerUserMap().get(k);
                    }
                    RelativesProto.RelativesTempMsg.Builder builder = RelativesPb.parseRelativesTempMsg(k, relatives, v, red);
                    if (builder != null) {
                        msg.addRelativesList(RelativesPb.parseRelativesTempMsg(k, relatives, v, red));
                    }
                }
            });
        }
        player.sendPacket(Protocol.U_RELATIVES_SYNC, msg);
    }

    /**
     * 计算需要显示的历史联姻
     */
    private boolean calHistoryMarriage(){
        if (relativesMap.size() == 0) {
            return false;
        }
        boolean needSync = false;
        List<RelativesInfo> datas = new ArrayList<>(relativesMap.values());
        datas.sort((o1, o2) -> o2.getMarriageTimes() - o1.getMarriageTimes());
        long userId = player.getUserId();
        Set<Long> ids = new HashSet<>();
        for (RelativesInfo info : datas) {
            if (info.getStatus() == 1) {
                continue;
            }
            if (ids.size() >= GameConfig.RELATIVES_MAX_HISTORY_NUM) {
                continue;
            }
            long relativesId;
            if (info.getUserId1() == userId) {
                relativesId = info.getUserId2();
            } else {
                relativesId = info.getUserId1();
            }
            if (!historyMarriageIds.contains(relativesId)) {
                needSync = true;
            }
            ids.add(relativesId);
        }
        historyMarriageIds.clear();
        historyMarriageIds.addAll(ids);
        return needSync;
    }

    /**
     * 同步联姻信息
     */
    public void syncMarriageData(long relativesId, RelativesInfo info, boolean isAddRelatives) {
        relativesMap.put(relativesId, info);

        //新增亲家从新推送亲家信息
        if (isAddRelatives) {
            syncRelativesData();
            return;
        }
        if (!historyMarriageIds.contains(relativesId)) {
            boolean needSync = calHistoryMarriage();
            if (needSync) {
                syncRelativesData();
            }
        } else {
            long serverId = GameServer.getInstance().getServerId();
            long relativeServerId = RelativesMgr.getUserServerId(relativesId);
            UserBaseInfo relatives;
            if(relativeServerId != serverId){
                relatives = RelativesMgr.getCacheOtherServerUserMap().get(relativesId);
            }else {
                relatives = UserMgr.getUserBaseInfo(relativesId, serverId);
            }
            if(relatives != null) {
                player.sendPacket(Protocol.U_RELATIVES_MARRIAGE_SYNC, RelativesPb.parseRelativesTempMsg(relativesId, relatives, info));
            }
        }
    }
    /**
     * 解除亲家
     * @param relativesId
     * @return
     */
    public int cancelRelatives(long relativesId) {
        if (!relativesMap.containsKey(relativesId)) {
            return GameErrorCode.E_RELATIVES_TIMES_NOT_ENOUGH;
        }
        RelativesInfo info = relativesMap.get(relativesId);
        if (info.getStatus() != 1) {
            return GameErrorCode.E_RELATIVES_TIMES_NOT_ENOUGH;
        }

        long relativesServerId = RelativesMgr.getUserServerId(relativesId);
        boolean isSameSerer = relativesServerId == GameServer.getInstance().getServerId();

        if(!isSameSerer) {
            //userBaseInfo = RelativesMgr.getCacheOtherServerUserMap().get(relativesId);
            //跨服解除亲家
            RelativesProto.CrossCancelRelativesReqMsg.Builder cancelReq = RelativesProto.CrossCancelRelativesReqMsg.newBuilder();
            cancelReq.setFromServerId(GameServer.getInstance().getServerId());
            cancelReq.setFromUserId(player.getUserId());
            cancelReq.setToServerId(relativesServerId);
            cancelReq.setRelativesId(relativesId);
            player.sendPacket(Protocol.C_RELATIVES_CANCEL, cancelReq);
            return -1;
        }

        info.setStatus((short) 0);
        info.setMarriageTimes(0);
        info.setLetterNum1(0);
        info.setLetterNum2(0);
        info.setIsShow("0,0");

        // 删除书信
        deleteLetter(relativesId);
        syncRelativesData();
        GamePlayer relativesPlayer = GamePlayerMgr.getOnlinePlayer(relativesId);
        if (relativesPlayer != null) {
            relativesPlayer.getModule(RelativesModule.class).deleteLetter(player.getUserId());
            relativesPlayer.getModule(RelativesModule.class).deleteGift(player.getUserId());
            relativesPlayer.getModule(RelativesModule.class).syncRelativesData();
            relativesPlayer.notifyListener(eGamePlayerEventType.RelativesCount.getValue(), RelativesMgr.getRelativesNum(relativesId));
        }
        player.notifyListener(eGamePlayerEventType.RelativesCount.getValue(), RelativesMgr.getRelativesNum(player.getUserId()));

        UserInfo userInfo = UserMgr.getUserInfo(relativesId);
        String mailTitle = MultipleLanguageMgr.getContent(MailManager.RELATIVES_CANCEL_TITLE, player.getLanguage());
        String mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.RELATIVES_CANCEL_CONTENT, player.getLanguage()), userInfo.getNickName());
        MailManager.sendMail(player.getUserId(), eMailType.SYSTEM.getValue(), "", mailContent, mailTitle);

        mailTitle = MultipleLanguageMgr.getContent(MailManager.RELATIVES_CANCEL_TITLE, userInfo.getLanguage());
        mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.RELATIVES_CANCEL_CONTENT, userInfo.getLanguage()), player.getUserInfo().getNickName());
        MailManager.sendMail(relativesId, eMailType.SYSTEM.getValue(), "", mailContent, mailTitle);

        return 0;
    }


    /**
     * 获取收到的书信
     * @return
     */
    public LinkedList<RelativesLetter> getLetters(long relativesId) {
        LinkedList<RelativesLetter> letters = letterMap.get(relativesId);
        if (letters == null) {
            return null;
        }
        LinkedList<RelativesLetter> receiveLetters = new LinkedList<>();
        for (RelativesLetter letter : letters) {
            if (!letter.isDelete() && letter.getFromId() == relativesId) {
                receiveLetters.addLast(letter);
            }
        }
        return receiveLetters;
    }

    /**
     * 获取所有的信件
     * @return
     */
    public LinkedList<RelativesLetter> getAllLetters(long relativesId) {
        LinkedList<RelativesLetter> letters = letterMap.get(relativesId);
        if (letters == null) {
            return null;
        }
        LinkedList<RelativesLetter> receiveLetters = new LinkedList<>();
        for (RelativesLetter letter : letters) {
            if (!letter.isDelete()) {
                receiveLetters.addLast(letter);
            }
        }
        return receiveLetters;
    }

    public RelativesInfo getRelativesInfo(long relativesId) {
        return relativesMap.get(relativesId);
    }
    public Map<Long, RelativesInfo> getRelativesMap() {
        return relativesMap;
    }

    /**
     * 解除亲家时删除书信
     * @param relativesId
     */
    public void deleteLetter(long relativesId) {
        LinkedList<RelativesLetter> letters = letterMap.get(relativesId);
        if (letters == null) {
            return;
        }
        for (RelativesLetter letter : letters) {
            letter.setDelete(true);
        }
    }


    /**
     * 写信
     * @return
     */
    public int writeLetter(long relativesId, String content) {
        RelativesInfo relativesInfo = getRelativesInfo(relativesId);
        // 判断写信还是回信
        int status = 0;
        if (relativesInfo.getUserId1() == player.getUserId()) {
            if (relativesInfo.getLetterNum1() < relativesInfo.getLetterNum2()) {
                status = 1;
            }
        } else {
            if (relativesInfo.getLetterNum1() > relativesInfo.getLetterNum2()) {
                status = 1;
            }
        }
        // 写信状态判断道具是否足够
        if (status == 0) {
            //消耗
            if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.RELATIVES_LETTER_PROP, BigInteger.valueOf(1)),
                    eLogMoneyType.Relatives, eLogMoneyType.RelativesLetter)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
        }
        RelativesLetter letter = RelativesMgr.createRelativesLetter(player.getUserId(), relativesId);
        letter.setContent(content);

        int writeNum = 0;
        if (relativesInfo.getUserId1() == player.getUserId()) {
            relativesInfo.setLetterNum1(relativesInfo.getLetterNum1()+1);
            writeNum = relativesInfo.getLetterNum1();
        } else {
            relativesInfo.setLetterNum2(relativesInfo.getLetterNum2()+1);
            writeNum = relativesInfo.getLetterNum2();
        }

        LinkedList<RelativesLetter> letters = letterMap.get(relativesId);
        if (letters == null) {
            letters = new LinkedList<>();
            letterMap.put(relativesId, letters);
        }
        letters.add(letter);

        //是否给跨服亲家写信
        long relativesUserServerId = RelativesMgr.getUserServerId(relativesId);
        if(relativesUserServerId != GameServer.getInstance().getServerId()){
            RelativesProto.CrossWriteLetterReqMsg.Builder crossReq = RelativesProto.CrossWriteLetterReqMsg.newBuilder();
            crossReq.setContent(content);
            crossReq.setToServerId(relativesUserServerId);
            crossReq.setRelativesId(relativesId);
            crossReq.setFromServerId(GameServer.getInstance().getServerId());
            crossReq.setFromUserId(player.getUserId());
            crossReq.setWriteNum(writeNum);
            player.sendPacket(Protocol.C_RELATIVES_WRITER_LETTER, crossReq);
            return 0;
        }

        //通知对方来信
        GamePlayer relativesPlayer = GamePlayerMgr.getOnlinePlayer(relativesId);
        if (relativesPlayer != null) {
            relativesPlayer.getModule(AttributeModule.class).addAttribute(ePlayerAttrType.TotalReceiveLetterCount, 1);
            relativesPlayer.getModule(RelativesModule.class).syncReceiveLetter(letter);
        }
        return 0;
    }

    /**
     * 收信通知
     * @param letter
     */
    public void syncReceiveLetter(RelativesLetter letter) {
        long receivesId = letter.getFromId();
        LinkedList<RelativesLetter> letters = letterMap.get(receivesId);
        if (letters == null) {
            letters = new LinkedList<>();
            letterMap.put(receivesId, letters);
        }
        letters.addLast(letter);

        //大于收信数时删除
        checkReceiveLetterNum(receivesId);

        RelativesProto.receiveLetterMsg.Builder msg = RelativesProto.receiveLetterMsg.newBuilder();
        msg.setRelativesId(receivesId);
        RelativesInfo relativesInfo = getRelativesInfo(receivesId);
        if (relativesInfo.getUserId1() == receivesId) {
            msg.setReceiveLetterNum(relativesInfo.getLetterNum1());
        } else {
            msg.setReceiveLetterNum(relativesInfo.getLetterNum2());
        }
        int redNum = 0;
        for (RelativesLetter data : letters) {
            if (!data.isShow() && data.getFromId() == receivesId) {
                redNum++;
            }
        }
        msg.setRedNum(redNum);
        player.sendPacket(Protocol.U_RELATIVES_GET_LETTER_SYNC, msg);
    }

    /**
     * 获取书信
     * @return
     */
    public RelativesLetter getLetter(long relativesId, long letterId) {
        for (RelativesLetter letter : letterMap.get(relativesId)) {
            if (letterId == letter.getId()) {
                return letter;
            }
        }
        return null;
    }

    /**
     * 当收信数量大于配置时删除之前的信
     * @param relativesId
     */
    private void checkReceiveLetterNum(long relativesId) {
        LinkedList<RelativesLetter> receiveLetters = getLetters(relativesId);
        int num = receiveLetters.size() - GameConfig.RELATIVES_LETTER_NUM;
        int index = 0;
        for(RelativesLetter letter : receiveLetters){
            if(num <= index){
                break;
            }
            letter.setDelete(true);
            index++;

        }
    }

    /**
     * 赠送
     * @param relativesId
     * @return
     */
    public int giveGift(long relativesId) {
        //跨服亲家
        long relativesServerId = RelativesMgr.getUserServerId(relativesId);
        if(relativesServerId != GameServer.getInstance().getServerId()){
            return sendCrossGift(relativesId, relativesServerId);
        }

        //放前面，防止查库频繁
        RelativesGift gift = giveMap.get(relativesId);
        if (gift != null) {
            return GameErrorCode.E_RELATIVES_GIVE_AGAIN_ERROR;
        }

        //对方不在线，会查库
        if (RelativesMgr.checkMaxReceiveOver(relativesId)) return GameErrorCode.E_RELATIVES_OTHER_RECEIVE_OVER;

        gift = RelativesMgr.createRelativesGift(player.getUserId(), relativesId);
        giveMap.put(relativesId, gift);

        GamePlayer relativesPlayer = GamePlayerMgr.getOnlinePlayer(relativesId);
        //同步对方收礼列表
        if (relativesPlayer != null) {
            relativesPlayer.getModule(RelativesModule.class).syncGiveGiftMsg(gift);
        }
        return 0;
    }

    public int sendCrossGift(long relativesId, long relativesServerId) {
        RelativesGift gift = giveMap.get(relativesId);
        if (gift != null) {
            return GameErrorCode.E_RELATIVES_GIVE_AGAIN_ERROR;
        }
        //冗余数据
        gift = RelativesMgr.createRelativesGift(player.getUserId(), relativesId);
        giveMap.put(relativesId, gift);

        RelativesProto.CrossGiveGiftReqMsg.Builder crossReq = RelativesProto.CrossGiveGiftReqMsg.newBuilder();
        crossReq.setFromServerId(GameServer.getInstance().getServerId());
        crossReq.setFromUserId(player.getUserId());
        crossReq.setRelativesId(relativesId);
        crossReq.setToServerId(relativesServerId);
        player.sendPacket(Protocol.C_RELATIVES_GIVE_GIFT, crossReq);
        return 0;
    }

    /**
     * 对方赠送赠礼消息
     * @param gift
     * @return
     */
    public void syncGiveGiftMsg(RelativesGift gift) {
        receiveMap.put(gift.getFromId(), gift);
        RelativesProto.ReceiveGiftMsg.Builder msg = RelativesProto.ReceiveGiftMsg.newBuilder();
        msg.setRelativesId(gift.getFromId());
        player.sendPacket(Protocol.U_RELATIVES_RECEIVE_GIFT_SYNC, msg);
    }

    /**
     * 解除亲家时如果赠礼未领取需要删除赠礼列表
     */
    public void deleteGift(long relativesId) {
        RelativesGift relativesGift = receiveMap.get(relativesId);
        if (relativesGift == null) {
            return;
        }
        if (relativesGift.isGet()) {
            return;
        }
        receiveMap.remove(relativesId);
        // 同步赠礼列表
        syncGiftList();
    }


    /**
     * 同步赠礼列表
     * @return
     */
    public void syncGiftList() {
        player.sendPacket(Protocol.U_RELATIVES_GIFT_LIST, RelativesPb.parseGiftTempMapMsg(giveMap, receiveMap));
    }

    /**
     * 领取
     * @param relativesId
     * @return
     */
    public int receiveGift(long relativesId) {
        RelativesGift gift = receiveMap.get(relativesId);

        if (gift == null) {
            return GameErrorCode.E_RELATIVES_NOT_GIFT;
        }
        if (gift.isGet()) {
            return GameErrorCode.E_RELATIVES_HAS_RECEIVE;
        }
        gift.setGet(true);
        return 0;
    }


    /**
     * 获取今日赠送或者领取次数
     * @param isGive
     * @return
     */
    public int getGiftTimes(boolean isGive) {
        int count = 0;
        int zeroTime = DateHelper.getTodayZeroTime();
        if (isGive) {
            for (RelativesGift gift : giveMap.values()) {
                if(gift.getLastTime() < zeroTime){
                    continue;
                }
                count++;
            }
        } else {
            for (RelativesGift gift : receiveMap.values()) {
                if(gift.getLastTime() < zeroTime){
                    continue;
                }
                if (gift.isGet()) {
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * 赠礼收礼每天凌晨重新载入数据
     */
    public void resetOneDay() {
        long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp() / 1000;
        boolean hasChange = false;

        Iterator<RelativesGift> iterator = giveMap.values().iterator();
        while (iterator.hasNext()) {
            RelativesGift relativesGift = iterator.next();
            if (relativesGift.getLastTime() < zeroTime) {
                hasChange = true;
                RelativesMgr.removeGiftData(relativesGift.getGiftId());
                iterator.remove();

            }
        }
        iterator = receiveMap.values().iterator();
        while (iterator.hasNext()) {
            RelativesGift relativesGift = iterator.next();
            if (relativesGift.getLastTime() < zeroTime) {
                hasChange = true;
                RelativesMgr.removeGiftData(relativesGift.getGiftId());
                iterator.remove();
            }
        }
        if (hasChange) {
            syncGiftList();
        }
    }

    public int getRelativesCount(){
        int count = 0;
        for(RelativesInfo relativesInfo : relativesMap.values()){
            if(1 == relativesInfo.getStatus()){
                count++;
            }
        }
        return count;
    }

    public Set<Long> getRelativesId() {
        Set<Long> list = new HashSet<>();
        for(RelativesInfo relativesInfo : relativesMap.values()){
            if(1 == relativesInfo.getStatus()){
                if (relativesInfo.getUserId1() != player.getUserId()) {
                    list.add(relativesInfo.getUserId1());
                }else  if (relativesInfo.getUserId2() != player.getUserId()) {
                    list.add(relativesInfo.getUserId2());
                }
            }
        }

        Map<Long, CrossUnionMember> memberMap = CrossUnionMgr.getUnionMemberMap(player.getUserInfo().getUnionUid());
        if (memberMap != null) {
            for (long userId : memberMap.keySet()) {
                if (userId != player.getUserId()) {
                    list.add(userId);
                }
            }
        }

        return list;
    }
}
